#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
@file_name: using_selectors_to_build_non_blocking_server.py
@date: 2025-07-29 14:27
@author: Falling Snow
@desc: 基于asyncio提供的selector模块构建一个非阻塞io的服务器
"""
import selectors
import socket
from typing import List, Tuple

if __name__ == '__main__':
    # 创建一个默认的selector对象
    selector = selectors.DefaultSelector()

    server_socket = socket.socket()
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SOCK_STREAM, 1)

    server_address = ("127.0.0.1", 8000)
    server_socket.bind(server_address)
    server_socket.setblocking(False)
    server_socket.listen()

    # 将服务端的这个socket注册到操作系统的事件系统中. 这里使用的是python封装的selector
    selector.register(server_socket, selectors.EVENT_READ)

    while True:
        # 创建一个selector, timeout表示最大的等待时间, 在等待的时间内, 如果遇到了对应的事件(上面定义的READ), 也会继续往下执行. 如果 <= 0, 则不等待, 如果传递None, 则变为block状态
        events: List[Tuple[selectors.SelectorKey, int]] = selector.select(timeout=10)

        if len(events) == 0:
            print("没有事件, 等待一会")
            continue

        for event, _ in events:
            # 从这个event中获取socket, 他是存储在fileobj这个字段中的
            event_socket = event.fileobj

            # 如果这个socket是我们的服务端socket, 表示有客户端连接
            if event_socket == server_socket:
                connection, address = server_socket.accept()
                connection.setblocking(False)
                print(f"来自{address}的链接")
                # 注册socket, 其次设置为Read事件.
                selector.register(connection, selectors.EVENT_READ)
            else:
                # 表示客户端发送了数据
                data = event_socket.recv(1024)
                print(f"我接受到了数据: {data.decode()}")
                event_socket.send(data)
